home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / USERTABL.C < prev    next >
C/C++ Source or Header  |  1991-11-21  |  12KB  |  317 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       u s e r t a b l . c                                          */
  3. /*                                                                    */
  4. /*       User table routines for UUPC/extended                        */
  5. /*                                                                    */
  6. /*       Copyright (C) 1989, 1990 by Andrew H. Derbyshire             */
  7. /*                                                                    */
  8. /*       See file README.SCR for restrictions on re-distribution.     */
  9. /*                                                                    */
  10. /*       History:                                                     */
  11. /*          Create from hostable.c                                    */
  12. /*--------------------------------------------------------------------*/
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <assert.h>
  18. #include <ctype.h>
  19. #include <sys/types.h>
  20.  
  21. #include "lib.h"
  22. #include "hlib.h"
  23. #include "usertabl.h"
  24. #include "hostable.h"
  25. #include "security.h"
  26.  
  27. #define MAXUSERS  100         /* max number of unique users in PASSWD */
  28.  
  29. struct UserTable *users = NULL;  /* Public to allow router.c to use it  */
  30.  
  31. size_t  UserElements = 0;        /* Public to allow router.c to use it  */
  32.  
  33. static size_t loaduser( void );
  34.  
  35. static int usercmp( const void *a , const void *b );
  36.  
  37. char *NextField( char *input );
  38.  
  39. static char uucpsh[] = UUCPSHELL;
  40.  
  41. currentfile();
  42.  
  43. /*--------------------------------------------------------------------*/
  44. /*    c h e c k u s e r                                               */
  45. /*                                                                    */
  46. /*    Look up a user name in the PASSWD file                          */
  47. /*--------------------------------------------------------------------*/
  48.  
  49. struct UserTable *checkuser(const char *name)
  50. {
  51.    int   lower;
  52.    int   upper;
  53.  
  54.    if ( (name == NULL) || (strlen(name) == 0) )
  55.    {
  56.       printmsg(0,"checkuser: Invalid argument!");
  57.       panic();
  58.    }
  59.  
  60.    printmsg(14,"checkuser: Searching for user id %s",name);
  61.  
  62.  /*------------------------------------------------------------------*/
  63.  /*             Initialize the host name table if needed             */
  64.  /*------------------------------------------------------------------*/
  65.  
  66.    if (UserElements == 0)           /* host table initialized yet?   */
  67.       UserElements = loaduser();        /* No --> load it            */
  68.  
  69.    lower = 0;
  70.    upper = UserElements - 1;
  71.  
  72. /*--------------------------------------------------------------------*/
  73. /*              Peform a binary search on the user table              */
  74. /*--------------------------------------------------------------------*/
  75.  
  76.    while ( lower <= upper )
  77.    {
  78.       int midpoint;
  79.       int hit;
  80.       midpoint = (lower + upper) / 2;
  81.  
  82.       hit = stricmp(name,users[midpoint].uid);
  83.  
  84.       if (hit > 0)
  85.          lower = midpoint + 1;
  86.       else if (hit < 0)
  87.          upper = midpoint - 1;
  88.       else
  89.          return &users[midpoint];
  90.    }
  91.  
  92. /*--------------------------------------------------------------------*/
  93. /*         We didn't find the user.  Return failure to caller         */
  94. /*--------------------------------------------------------------------*/
  95.  
  96.    return BADUSER;
  97.  
  98. }  /* checkuser */
  99.  
  100.  
  101. /*--------------------------------------------------------------------*/
  102. /*    i n i t u s e r                                                 */
  103. /*                                                                    */
  104. /*    Intializes a user table entry for for loaduser                  */
  105. /*--------------------------------------------------------------------*/
  106.  
  107. struct UserTable *inituser(char *name)
  108. {
  109.  
  110.    size_t hit = UserElements;
  111.    size_t element = 0;
  112.  
  113.    if (users == NULL)
  114.    {
  115.       users = calloc(MAXUSERS, sizeof(*users));
  116.       checkref(users);
  117.    }
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*    Add the user to the table.  Note that we must add the user      */
  121. /*    to the table ourselves (rather than use lsearch) because we     */
  122. /*    must make a copy of the string; the *token we use for the       */
  123. /*    search is in the middle of our I/O buffer!                      */
  124. /*--------------------------------------------------------------------*/
  125.  
  126.    while ( element < hit )
  127.    {
  128.       if (equali( users[element].uid , name ))
  129.          hit = element;
  130.       else
  131.          element++;
  132.    }
  133.  
  134.    if (hit == UserElements)
  135.    {
  136.       users[hit].uid      = strdup(name);
  137.       checkref(users[hit].uid);
  138.       users[hit].realname = "????";
  139.       users[hit].beep     = NULL;
  140.       users[hit].homedir  = pubdir;
  141.       users[hit].hsecure  = NULL;
  142.       users[hit].password = NULL;
  143.       users[hit].sh       = uucpsh;
  144.       assert(UserElements++ < MAXUSERS);
  145.    } /* if */
  146.  
  147.    return &users[hit];
  148.  
  149. } /* inituser */
  150.  
  151. /*--------------------------------------------------------------------*/
  152. /*    l o a d u s e r                                                 */
  153. /*                                                                    */
  154. /*    Load the user password file                                     */
  155. /*--------------------------------------------------------------------*/
  156.  
  157. static size_t loaduser( void )
  158. {
  159.    char s_systems[FILENAME_MAX];
  160.    FILE *stream;
  161.    struct UserTable *userp;
  162.    size_t hit;
  163.    char buf[BUFSIZ];
  164.    char *token;
  165.  
  166. /*--------------------------------------------------------------------*/
  167. /*     First, load in the active user as first user in the table      */
  168. /*--------------------------------------------------------------------*/
  169.  
  170.    userp = inituser( mailbox );
  171.    userp->realname = name;
  172.    userp->homedir  = homedir;
  173.  
  174. /*--------------------------------------------------------------------*/
  175. /*       Password file format:                                        */
  176. /*          user id:password:::user/system name:homedir:shell         */
  177. /*--------------------------------------------------------------------*/
  178.  
  179.    mkfilename(s_systems, confdir, PASSWD);
  180.  
  181.    if ((stream = FOPEN(s_systems, "r", TEXT)) == NULL)
  182.    {
  183.       printmsg(2,"loaduser: Cannot open password file %s",s_systems);
  184.       users = realloc(users, UserElements *  sizeof(*users));
  185.       checkref(users);
  186.       return UserElements;
  187.    } /* if */
  188.  
  189. /*--------------------------------------------------------------------*/
  190. /*                 The password file is open; read it                 */
  191. /*--------------------------------------------------------------------*/
  192.  
  193.    while (! feof(stream)) {
  194.       if (fgets(buf,BUFSIZ,stream) == NULL)   /* Try to read a line      */
  195.          break;               /* Exit if end of file                 */
  196.       if ((*buf == '#') || (*buf == '\0'))
  197.          continue;            /* Line is a comment; loop again       */
  198.       if ( buf[ strlen(buf) - 1 ] == '\n')
  199.          buf[ strlen(buf) - 1 ] = '\0';
  200.       token = NextField(buf);
  201.       if (token    == NULL)   /* Any data?                           */
  202.          continue;            /* No --> read another line            */
  203.       userp = inituser(token);/* Initialize record for user          */
  204.  
  205.       if (userp->password != NULL)  /* Does the user already exist?  */
  206.       {                       /* Yes --> Report and ignore           */
  207.          printmsg(0,"loaduser: Duplicate entry for '%s' in '%s' ignored",
  208.                token,s_systems);
  209.          continue;            /* System already in /etc/passwd,
  210.                                  ignore it.                          */
  211.       }
  212.  
  213.       token = NextField(NULL);   /* Get the user password            */
  214.       if (!equal(token,"*"))     /* User can login?                  */
  215.          userp->password = strdup(token); /* Yes --> Set password    */
  216.  
  217.       token = NextField(NULL);   /* Use  UNIX user number as tone    */
  218.                                  /* to beep at                       */
  219.       if (token != NULL)
  220.          userp->beep = strdup( token );
  221.  
  222.       token = NextField(NULL);   /* Skip UNIX group number           */
  223.  
  224.       token = NextField(NULL);   /* Get the formal user name         */
  225.       if (token != NULL)         /* Did they provide user name?      */
  226.     userp->realname = strdup(token); /* Yes --> Copy            */
  227.  
  228.       token = NextField(NULL);   /* Get home directory (optional)    */
  229.       if ( token != NULL)
  230.          userp->homedir = strdup(token);
  231.  
  232.       token = NextField(NULL);   /* Get user shell (optional)        */
  233.       if ( token != NULL )       /* Did we get it?                   */
  234.          userp->sh = strdup(token); /* Yes --> Copy it in            */
  235.  
  236.    }  /* while */
  237.  
  238.    fclose(stream);
  239.    users = realloc(users, UserElements *  sizeof(*users));
  240.    checkref(users);
  241.  
  242.    qsort(users, UserElements ,sizeof(users[0]) , usercmp);
  243.  
  244.    for (hit = 0 ; hit < UserElements; hit ++)
  245.    {
  246.       printmsg(8,"loaduser: user[%d] user id(%s) no(%s) name(%s) \
  247. home directory(%s) shell(%s)",
  248.          hit,
  249.          users[hit].uid,
  250.          users[hit].beep == NULL ? "NONE" : users[hit].beep,
  251.          users[hit].realname,
  252.          users[hit].homedir,
  253.          users[hit].sh);
  254.    } /* for */
  255.  
  256.    return UserElements;
  257. } /* loaduser */
  258.  
  259. /*--------------------------------------------------------------------*/
  260. /*    u s e r c m p                                                   */
  261. /*                                                                    */
  262. /*    Accepts indirect pointers to two strings and compares           */
  263. /*    them using stricmp (case insensitive string compare)            */
  264. /*--------------------------------------------------------------------*/
  265.  
  266. int usercmp( const void *a , const void *b )
  267. {
  268.    return stricmp(((struct UserTable*) a)->uid,
  269.         ((struct UserTable*) b)->uid);
  270. }  /*usercmp*/
  271.  
  272. /*--------------------------------------------------------------------*/
  273. /*    n e x t f i e l d                                               */
  274. /*                                                                    */
  275. /*    Find the next field in the user password file                   */
  276. /*--------------------------------------------------------------------*/
  277.  
  278. char *NextField( char *input )
  279. {
  280.    static char *start = NULL;
  281.    char *next = NULL;
  282.  
  283.    if (input == NULL)         /* Starting a new field?               */
  284.    {
  285.       if ( start  == NULL )   /* Anything left to parse?             */
  286.          return NULL;         /* No --> Return empty string          */
  287.       else
  288.          input = start;       /* Yes --> Continue parse of old one   */
  289.    } /* if */
  290.  
  291. /*--------------------------------------------------------------------*/
  292. /*    Look for the next field; because MS-DOS directories may have    */
  293. /*    a sequence of x:/ or x:\ where 'x' is a drive letter, we take   */
  294. /*    special care to allow DOS directories to appear unmolested      */
  295. /*    in the password file                                            */
  296. /*--------------------------------------------------------------------*/
  297.  
  298.    if ((strlen(input) > 2) && isalpha(input[0]) && (input[1] == ':') &&
  299.        ((input[2] == '/') || (input[2] == '\\')))
  300.       next = strchr( &input[2], ':');   /* Find start of next field  */
  301.    else
  302.       next = strchr( input, ':');   /* Find start of next field      */
  303.  
  304.    if (next == NULL )         /* Last field?                         */
  305.       start = NULL;           /* Yes --> Make next call return NULL  */
  306.    else {                     /* No                                  */
  307.       *next = '\0';           /* Terminate the string                */
  308.       start = ++next;         /* Have next call look at next field   */
  309.    } /* else */
  310.  
  311.    if (strlen(input))         /* Did we get anything in the field?   */
  312.       return input;           /* Yes --> Return the string           */
  313.    else
  314.       return NULL;            /* Field is empty, return NULL         */
  315.  
  316. } /* NextField */
  317.